import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

/// 键盘监听
class KqRawKeyboardListener extends StatefulWidget {
  /// 是否开启监听，默认true
  final bool enable;

  /// 子控件
  final Widget child;

  /// 如果没有扫码枪不会模拟回车，则延迟500ms自动提交，默认开启
  final bool enableTimer;

  /// 扫码回调
  final Function(String scanContent)? onScanCallback;

  const KqRawKeyboardListener(
      {Key? key,
      required this.child,
      this.enable = true,
      this.enableTimer = true,
      this.onScanCallback})
      : super(key: key);

  @override
  KqRawKeyboardListenerState createState() => KqRawKeyboardListenerState();
}

class KqRawKeyboardListenerState extends State<KqRawKeyboardListener> {
  String scanContent = '';

  Timer? timer;

  @override
  void initState() {
    scanContent = '';
    if (widget.enable) {
      RawKeyboard.instance.addListener(_handleRawKeyEvent);
    }
    super.initState();
  }

  @override
  void didUpdateWidget(covariant KqRawKeyboardListener oldWidget) {
    if (oldWidget.enable != widget.enable) {
      if (widget.enable) {
        RawKeyboard.instance.addListener(_handleRawKeyEvent);
      } else {
        RawKeyboard.instance.removeListener(_handleRawKeyEvent);
      }
    }
    super.didUpdateWidget(oldWidget);
  }

  @override
  Widget build(BuildContext context) {
    return widget.child;
  }

  _handleRawKeyEvent(RawKeyEvent event) {
    timer?.cancel();
    dynamic eventData = event.data;
    if (eventData is RawKeyEventDataAndroid && event is RawKeyDownEvent) {
      if (eventData.keyCode == 66) {
        //回车键
        if (widget.onScanCallback != null) {
          widget.onScanCallback!(scanContent);
        }
        scanContent = '';
      } else {
        //部分扫码枪会扫出来一些夹杂codePoint==0的的event，必须排除。
        if (eventData.codePoint != 0) {
          String chars = _analysisKeyEvent(event, eventData);
          if (chars.isNotEmpty) {
            scanContent = '$scanContent$chars';
          }
        }
        if (widget.enableTimer) {
          timer = Timer(const Duration(milliseconds: 500), () {
            if (widget.onScanCallback != null && scanContent.isNotEmpty) {
              widget.onScanCallback!(scanContent);
            }
            scanContent = '';
          });
        }
      }
    }
  }

  @override
  void dispose() {
    super.dispose();
    timer?.cancel();
    RawKeyboard.instance.removeListener(_handleRawKeyEvent);
  }

  /// 按钮转码
  String _analysisKeyEvent(RawKeyDownEvent event, RawKeyEventDataAndroid data) {
    String str = '';
    /* 键盘第一行 */
    // ~ `
    if (PhysicalKeyboardKey.backquote == event.physicalKey) {
      str = event.isShiftPressed ? '~' : '`';
    }
    // 1 !
    else if (PhysicalKeyboardKey.digit1 == event.physicalKey) {
      str = event.isShiftPressed ? '!' : '1';
    }
    // 2 @
    else if (PhysicalKeyboardKey.digit2 == event.physicalKey) {
      str = event.isShiftPressed ? '@' : '2';
    }
    // 3 #
    else if (PhysicalKeyboardKey.digit3 == event.physicalKey) {
      str = event.isShiftPressed ? '#' : '3';
    }
    // 4 $
    else if (PhysicalKeyboardKey.digit4 == event.physicalKey) {
      str = event.isShiftPressed ? r'$' : '4';
    }
    // 5 %
    else if (PhysicalKeyboardKey.digit5 == event.physicalKey) {
      str = event.isShiftPressed ? '%' : '5';
    }
    // 6 ^
    else if (PhysicalKeyboardKey.digit6 == event.physicalKey) {
      str = event.isShiftPressed ? '^' : '6';
    }
    // 7 &
    else if (PhysicalKeyboardKey.digit7 == event.physicalKey) {
      str = event.isShiftPressed ? '&' : '7';
    }
    // 8 *
    else if (PhysicalKeyboardKey.digit8 == event.physicalKey) {
      str = event.isShiftPressed ? '*' : '8';
    }
    // 9 (
    else if (PhysicalKeyboardKey.digit9 == event.physicalKey) {
      str = event.isShiftPressed ? '(' : '9';
    }
    // 0 )
    else if (PhysicalKeyboardKey.digit0 == event.physicalKey) {
      str = event.isShiftPressed ? ')' : '0';
    }
    // - _
    else if (PhysicalKeyboardKey.minus == event.physicalKey) {
      str = event.isShiftPressed ? '_' : '-';
    }
    // = +
    else if (PhysicalKeyboardKey.equal == event.physicalKey) {
      str = event.isShiftPressed ? '+' : '=';
    }
    /* 键盘第二行 */
    // Q q
    else if (PhysicalKeyboardKey.keyQ == event.physicalKey) {
      str = event.isShiftPressed ? 'Q' : 'q';
    }
    // W w
    else if (PhysicalKeyboardKey.keyW == event.physicalKey) {
      str = event.isShiftPressed ? 'W' : 'w';
    }
    // E e
    else if (PhysicalKeyboardKey.keyE == event.physicalKey) {
      str = event.isShiftPressed ? 'E' : 'e';
    }
    // R r
    else if (PhysicalKeyboardKey.keyR == event.physicalKey) {
      str = event.isShiftPressed ? 'R' : 'r';
    }
    // T t
    else if (PhysicalKeyboardKey.keyT == event.physicalKey) {
      str = event.isShiftPressed ? 'T' : 't';
    }
    // Y y
    else if (PhysicalKeyboardKey.keyY == event.physicalKey) {
      str = event.isShiftPressed ? 'Y' : 'y';
    }
    // U u
    else if (PhysicalKeyboardKey.keyU == event.physicalKey) {
      str = event.isShiftPressed ? 'U' : 'u';
    }
    // I i
    else if (PhysicalKeyboardKey.keyI == event.physicalKey) {
      str = event.isShiftPressed ? 'I' : 'i';
    }
    // O o
    else if (PhysicalKeyboardKey.keyO == event.physicalKey) {
      str = event.isShiftPressed ? 'O' : 'o';
    }
    // P p
    else if (PhysicalKeyboardKey.keyP == event.physicalKey) {
      str = event.isShiftPressed ? 'P' : 'p';
    }
    // { [
    else if (PhysicalKeyboardKey.bracketLeft == event.physicalKey) {
      str = event.isShiftPressed ? '{' : '[';
    }
    // } ]
    else if (PhysicalKeyboardKey.bracketRight == event.physicalKey) {
      str = event.isShiftPressed ? '}' : ']';
    }
    // | \
    else if (PhysicalKeyboardKey.backslash == event.physicalKey) {
      str = event.isShiftPressed ? '|' : r'\';
    }
    /* 键盘第三行 */
    // A a
    else if (PhysicalKeyboardKey.keyA == event.physicalKey) {
      str = event.isShiftPressed ? 'A' : 'a';
    }
    // S s
    else if (PhysicalKeyboardKey.keyS == event.physicalKey) {
      str = event.isShiftPressed ? 'S' : 's';
    }
    // D d
    else if (PhysicalKeyboardKey.keyD == event.physicalKey) {
      str = event.isShiftPressed ? 'D' : 'd';
    }
    // F f
    else if (PhysicalKeyboardKey.keyF == event.physicalKey) {
      str = event.isShiftPressed ? 'F' : 'f';
    }
    // G g
    else if (PhysicalKeyboardKey.keyG == event.physicalKey) {
      str = event.isShiftPressed ? 'G' : 'g';
    }
    // H h
    else if (PhysicalKeyboardKey.keyH == event.physicalKey) {
      str = event.isShiftPressed ? 'H' : 'h';
    }
    // J j
    else if (PhysicalKeyboardKey.keyJ == event.physicalKey) {
      str = event.isShiftPressed ? 'J' : 'j';
    }
    // K k
    else if (PhysicalKeyboardKey.keyK == event.physicalKey) {
      str = event.isShiftPressed ? 'K' : 'k';
    }
    // L l
    else if (PhysicalKeyboardKey.keyL == event.physicalKey) {
      str = event.isShiftPressed ? 'L' : 'l';
    }
    // : ;
    else if (PhysicalKeyboardKey.semicolon == event.physicalKey) {
      str = event.isShiftPressed ? ':' : ';';
    }
    // " '
    else if (PhysicalKeyboardKey.quote == event.physicalKey) {
      str = event.isShiftPressed ? '"' : '\'';
    }
    /* 键盘第四行 */
    // Z z
    else if (PhysicalKeyboardKey.keyZ == event.physicalKey) {
      str = event.isShiftPressed ? 'Z' : 'z';
    }
    // X x
    else if (PhysicalKeyboardKey.keyX == event.physicalKey) {
      str = event.isShiftPressed ? 'X' : 'x';
    }
    // C c
    else if (PhysicalKeyboardKey.keyC == event.physicalKey) {
      str = event.isShiftPressed ? 'C' : 'c';
    }
    // V v
    else if (PhysicalKeyboardKey.keyV == event.physicalKey) {
      str = event.isShiftPressed ? 'V' : 'v';
    }
    // B b
    else if (PhysicalKeyboardKey.keyB == event.physicalKey) {
      str = event.isShiftPressed ? 'B' : 'b';
    }
    // N n
    else if (PhysicalKeyboardKey.keyN == event.physicalKey) {
      str = event.isShiftPressed ? 'N' : 'n';
    }
    // M m
    else if (PhysicalKeyboardKey.keyM == event.physicalKey) {
      str = event.isShiftPressed ? 'M' : 'm';
    }
    // < ,
    else if (PhysicalKeyboardKey.comma == event.physicalKey) {
      str = event.isShiftPressed ? '<' : ',';
    }
    // > .
    else if (PhysicalKeyboardKey.period == event.physicalKey) {
      str = event.isShiftPressed ? '>' : '.';
    }
    // ? /
    else if (PhysicalKeyboardKey.slash == event.physicalKey) {
      str = event.isShiftPressed ? '?' : '/';
    }
    /* 键盘第五行 */
    // 空格
    else if (PhysicalKeyboardKey.space == event.physicalKey) {
      str = ' ';
    }
    /* 小键盘 */
    // 0
    else if (PhysicalKeyboardKey.numpad0 == event.physicalKey) {
      str = '0';
    }
    // 1
    else if (PhysicalKeyboardKey.numpad1 == event.physicalKey) {
      str = '1';
    }
    // 2
    else if (PhysicalKeyboardKey.numpad2 == event.physicalKey) {
      str = '2';
    }
    // 3
    else if (PhysicalKeyboardKey.numpad3 == event.physicalKey) {
      str = '3';
    }
    // 4
    else if (PhysicalKeyboardKey.numpad4 == event.physicalKey) {
      str = '4';
    }
    // 5
    else if (PhysicalKeyboardKey.numpad5 == event.physicalKey) {
      str = '5';
    }
    // 6
    else if (PhysicalKeyboardKey.numpad6 == event.physicalKey) {
      str = '6';
    }
    // 7
    else if (PhysicalKeyboardKey.numpad7 == event.physicalKey) {
      str = '7';
    }
    // 8
    else if (PhysicalKeyboardKey.numpad8 == event.physicalKey) {
      str = '8';
    }
    // 9
    else if (PhysicalKeyboardKey.numpad9 == event.physicalKey) {
      str = '9';
    }
    // +
    else if (PhysicalKeyboardKey.numpadAdd == event.physicalKey) {
      str = '+';
    }
    // -
    else if (PhysicalKeyboardKey.numpadSubtract == event.physicalKey) {
      str = '-';
    }
    // *
    else if (PhysicalKeyboardKey.numpadMultiply == event.physicalKey) {
      str = '*';
    }
    // /
    else if (PhysicalKeyboardKey.numpadDivide == event.physicalKey) {
      str = '/';
    }
    // .
    else if (PhysicalKeyboardKey.numpadDecimal == event.physicalKey) {
      str = '.';
    } else {
      str = String.fromCharCode(data.codePoint);
    }
    return str;
  }
}
